﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Features2D;
using Emgu.CV.Structure;
using Emgu.CV.UI;
using Emgu.CV.Util;
using Emgu.CV.GPU;
using Emgu.Util;
using System.Diagnostics;


namespace csCircleDetect
{
    public partial class Form1 : Form
    {
        private Capture _capture;
        private bool _captureInProgress;
        private CircleF[] cirarray;
        private Rectangle[] recarray = new Rectangle[32];
        private Size sizeimg = new Size(130, 130);
        private Image<Bgr, Byte> outimg;
        private Image<Gray, Byte>[] templator;
        private String[] nametemplator = new String[32];
        private int rectnumber;
        private int x, y;
        private MCvFont f = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_COMPLEX, 1.0, 1.0);
        

       
        
        //private Image<Bgr, Byte> img = new Image<Bgr, byte>(fileNameTextBox.Text);
        public Form1()
        {
            InitializeComponent();
            fileNameTextBox.Text = "Image19.jpg";
            y = circleImageBox.Height;
            x = circleImageBox.Width;
            
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
        
       
        private Image<Bgr,Byte> circledetect(Image<Bgr, Byte> imgin)
        {
            StringBuilder msgBuilder = new StringBuilder("Performance: ");

            //Load the image from file and resize it for display


            //remember this
            Image<Bgr, Byte> img;
            img = imgin;

            //outimg = img;

            // .Resize(400, 400, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR, true);

            //Convert the image to grayscale and filter out the noise
            Image<Gray, Byte> gray = img.Convert<Gray, Byte>().PyrDown().PyrUp();

            #region circle detection
            // Stopwatch watch = Stopwatch.StartNew();
            Gray cannyThreshold = new Gray(180);
            Gray cannyThresholdLinking = new Gray(120);
            Gray circleAccumulatorThreshold = new Gray(500);


            
             //on dinh
            CircleF[] circles = gray.HoughCircles(
                cannyThreshold,
                circleAccumulatorThreshold,
                4.0, //Resolution of the accumulator used to detect centers of the circles
                10.0, //min distance 
                // 15,//min distance for examples
                20, //min radius//best value for vaio 1 gang tay.//15
                40 //max radius//30
                )[0]; //Get the circles from the first channel

            //watch.Stop();
            //msgBuilder.Append(String.Format("Hough circles - {0} ms; ", watch.ElapsedMilliseconds));
             

           /* 
            //new
            CircleF[] circles = gray.HoughCircles(
                cannyThreshold,
                circleAccumulatorThreshold,
                4.0, //Resolution of the accumulator used to detect centers of the circles
                10.0, //min distance 
                // 15,//min distance for examples
                25, //min radius//best value for vaio 1 gang tay.
                55 //max radius
                )[0]; //Get the circles from the first channel

            //watch.Stop();
            //msgBuilder.Append(String.Format("Hough circles - {0} ms; ", watch.ElapsedMilliseconds));
            */
            #endregion

            /*
            #region draw circles
            Image<Bgr, Byte> circleImage = img.CopyBlank();
            foreach (CircleF circle in circles)
               img.Draw(circle, new Bgr(Color.Brown), 2);
            circleImageBox.Image = img.ToBitmap();
            #endregion
             */

            cirarray = circles;

            for (int i = 0; i < circles.Length; i++)
            {

                //circle.Center = circle.Center + (10,10);
                //vi phat hien ra hinh tron khong chinh xac nen ta phai chinh sua toa do tam va ban kinh lai de ve
                rectnumber++;
                PointF pnt = circles[i].Center;//khai bao diem pnt thuoc class PointF
                pnt.X += 5;//tang x
                pnt.Y += 7;//tang y
                //circle.Center=pnt;


                CircleF circleshow = new CircleF(circles[i].Center, circles[i].Radius + 3);//khai bao duong tron circleshow voi tam va ban kinh +4 so voi circle, khong thay doi circle duoc nen ta phai dung circleshow tam
                circleshow.Center = pnt;//gan tam cua duong tron moi vao la diem moi duoc thay doi
                //img.Draw(circleshow, new Bgr(Color.Brown), 2);//ve duong tron mau nau va thickness = 2(ve de len anh)

                cirarray[i].Center = pnt;
                cirarray[i].Radius = circleshow.Radius;

                int rad; //tao bien rad
                rad = (int)circleshow.Radius; //lay gia tri chuyen thanh int 
                recarray[i].X = (int)circleshow.Center.X - rad - 3; //tinh toa do x cua goc trai tren hinh chu nhat
                recarray[i].Y = (int)circleshow.Center.Y - rad - 3; //tinh toa do y cua goc trai tren hinh chu nhat
                recarray[i].Width = 2 * rad + 12;
                recarray[i].Height = 2 * rad+ 12;

                img.Draw(recarray[i], new Bgr(Color.Blue), 2);
                //img.Draw("a", new MCvFont(CV_FONT_HERSHEY_SIMPLEX, 1, 1), recarray[i].X, new Bgr(Color.Red));
                img.Draw(i.ToString(), ref f, recarray[i].Location, new Bgr(0, 255, 0));

                //cirarray[i] = circles[i];
                //Rectangle Xyz = new Rectangle();
            }

            //circleImageBox.Image = img.ToBitmap();//xuat ra imagebox
            return img;

        }
        private void button1_Click(object sender, EventArgs e)
        {
            
            StringBuilder msgBuilder = new StringBuilder("Performance: ");

            //Load the image from file and resize it for display


            //remember this
            Image<Bgr, Byte> img = new Image<Bgr, Byte>(fileNameTextBox.Text);

            outimg = img;

              // .Resize(400, 400, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR, true);

            //Convert the image to grayscale and filter out the noise
            Image<Gray, Byte> gray = img.Convert<Gray, Byte>().PyrDown().PyrUp();

            #region circle detection
           // Stopwatch watch = Stopwatch.StartNew();
            Gray cannyThreshold = new Gray(180);
            Gray cannyThresholdLinking = new Gray(120);
            Gray circleAccumulatorThreshold = new Gray(500);
            CircleF[] circles = gray.HoughCircles(
                cannyThreshold,
                circleAccumulatorThreshold,
                4.0, //Resolution of the accumulator used to detect centers of the circles
                15.0, //min distance 
               // 15,//min distance for examples
                27, //min radius//
                50 //max radius
                )[0]; //Get the circles from the first channel
            //watch.Stop();
            //msgBuilder.Append(String.Format("Hough circles - {0} ms; ", watch.ElapsedMilliseconds));
            #endregion

            /*
            #region draw circles
            Image<Bgr, Byte> circleImage = img.CopyBlank();
            foreach (CircleF circle in circles)
               circleImage.Draw(circle, new Bgr(Color.Brown), 2);
            circleImageBox.Image = circleImage.ToBitmap();
            #endregion
              */
             

            //coded by me
           /*
            foreach (CircleF circle in circles)
           {
               //circle.Center = circle.Center + (10,10);
               //vi phat hien ra hinh tron khong chinh xac nen ta phai chinh sua toa do tam va ban kinh lai de ve
               PointF pnt = circle.Center;//khai bao diem pnt thuoc class PointF
               pnt.X += 7;//tang x
               pnt.Y += 6;//tang y
               //circle.Center=pnt;


               CircleF circleshow = new CircleF(circle.Center,circle.Radius+2);//khai bao duong tron circleshow voi tam va ban kinh +4 so voi circle, khong thay doi circle duoc nen ta phai dung circleshow tam
               circleshow.Center = pnt;//gan tam cua duong tron moi vao la diem moi duoc thay doi
               img.Draw(circleshow, new Bgr(Color.Brown), 2);//ve duong tron mau nau va thickness = 2(ve de len anh)
           }
             */
            cirarray = circles;

            for (int i = 0; i < circles.Length; i++)
            {
                
               //circle.Center = circle.Center + (10,10);
               //vi phat hien ra hinh tron khong chinh xac nen ta phai chinh sua toa do tam va ban kinh lai de ve
               PointF pnt = circles[i].Center;//khai bao diem pnt thuoc class PointF
               pnt.X += 5;//tang x
               pnt.Y += 7;//tang y
               //circle.Center=pnt;
               

               CircleF circleshow = new CircleF(circles[i].Center, circles[i].Radius + 2);//khai bao duong tron circleshow voi tam va ban kinh +4 so voi circle, khong thay doi circle duoc nen ta phai dung circleshow tam
               circleshow.Center = pnt;//gan tam cua duong tron moi vao la diem moi duoc thay doi
               img.Draw(circleshow, new Bgr(Color.Brown), 2);//ve duong tron mau nau va thickness = 2(ve de len anh)

                cirarray[i].Center = pnt;
                cirarray[i].Radius = circleshow.Radius;

               //cirarray[i] = circles[i];

           }

            circleImageBox.Image = img.ToBitmap();//xuat ra imagebox
        }


        private void ProcessFrame(object sender, EventArgs arg)
        {
            Image<Bgr, Byte> img = _capture.QueryFrame();

            StringBuilder msgBuilder = new StringBuilder("Performance: ");

            //Load the image from file and resize it for display
       
            // .Resize(400, 400, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR, true);

            //Convert the image to grayscale and filter out the noise
            Image<Gray, Byte> gray = img.Convert<Gray, Byte>().PyrDown().PyrUp();

            #region circle detection
            // Stopwatch watch = Stopwatch.StartNew();
            Gray cannyThreshold = new Gray(180);
            Gray cannyThresholdLinking = new Gray(120);
            Gray circleAccumulatorThreshold = new Gray(500);
            CircleF[] circles = gray.HoughCircles(
                cannyThreshold,
                circleAccumulatorThreshold,
                4.0, //Resolution of the accumulator used to detect centers of the circles
                15.0, //min distance 
                27, //min radius
                50 //max radius
                )[0]; //Get the circles from the first channel
            //watch.Stop();
            //msgBuilder.Append(String.Format("Hough circles - {0} ms; ", watch.ElapsedMilliseconds));
            #endregion

            /*
            #region draw circles
            Image<Bgr, Byte> circleImage = img.CopyBlank();
            foreach (CircleF circle in circles)
               circleImage.Draw(circle, new Bgr(Color.Brown), 2);
            circleImageBox.Image = circleImage.ToBitmap();
            #endregion
              */


            //coded by me
            foreach (CircleF circle in circles)
            {
                //circle.Center = circle.Center + (10,10);
                //vi phat hien ra hinh tron khong chinh xac nen ta phai chinh sua toa do tam va ban kinh lai de ve
                PointF pnt = circle.Center;//khai bao diem pnt thuoc class PointF
                pnt.X += 6;//tang x
                pnt.Y += 7;//tang y
                //circle.Center=pnt;
                CircleF circleshow = new CircleF(circle.Center, circle.Radius + 4);//khai bao duong tron circleshow voi tam va ban kinh +4 so voi circle, khong thay doi circle duoc nen ta phai dung circleshow tam
                circleshow.Center = pnt;//gan tam cua duong tron moi vao la diem moi duoc thay doi
                img.Draw(circleshow, new Bgr(Color.Brown), 2);//ve duong tron mau nau va thickness = 2(ve de len anh)
            }
            //Image<Bgr, Byte> testimg = new Image<Bgr, Byte>(outimg);
            //outimg = img.Copy(img);
            circleImageBox.Image = img.ToBitmap();//xuat ra imagebox

          
        }

        private void button2_Click(object sender, EventArgs e)
        {
            #region if capture is not created, create it now
            if (_capture == null)
            {
                try
                {
                    _capture = new Capture(1);
                }
                catch (NullReferenceException excpt)
                {
                    MessageBox.Show(excpt.Message);
                }
            }
            #endregion

            if (_capture != null)
            {
                if (_captureInProgress)
                {  //stop the capture
                    //captureButton.Text = "Start Capture";
                    Application.Idle -= ProcessFrame;
                }
                else
                {
                    //start the capture
                    //captureButton.Text = "Stop";
                    Application.Idle += ProcessFrame;
                }

                _captureInProgress = !_captureInProgress;
            }
        }



        
 

        private void button3_Click(object sender, EventArgs e)
        {
            //Image<Bgr, Byte> imagenew = new Image<Bgr, Byte>(pic1.Size);
            Image<Bgr, Byte> src = new Image<Bgr, Byte>(outimg.Size);
            Image<Gray, Byte> roi = new Image<Gray, Byte>(outimg.Size);
            Image<Gray, Byte> roic3 = new Image<Gray, Byte>(outimg.Size);
            Image<Bgr, Byte> res = new Image<Bgr, Byte>(outimg.Size);
            Image<Bgr, Byte> res1 = new Image<Bgr, Byte>(80,80);
            //Image<Bgr,Byte> roi = CvInvoke.cvCreateImage(sizeimg, 8, 1);

            src = outimg;

            MCvScalar a = new MCvScalar(250, 110, 100);

            CvInvoke.cvZero(roi.Ptr);
            CvInvoke.cvZero(res.Ptr);




            #region testnew
            int x = (int)cirarray[0].Center.X;
            int y = (int)cirarray[0].Center.Y;
            Point pnt1 = new Point(x, y);
            CvInvoke.cvCircle(roi.Ptr, pnt1, (int)cirarray[0].Radius, a, -1, LINE_TYPE.EIGHT_CONNECTED, 0);
            CvInvoke.cvCopy(src, res, roi);

            pic1.Image = roi.ToBitmap();
            pic2.Image = res.ToBitmap();
            #endregion

            /*
            #region test
            //int x = (int)cirarray[0].Center.X;
            //int y = (int)cirarray[0].Center.Y;
            foreach (CircleF cirarraysub in cirarray)
            {
                int x = (int)cirarraysub.Center.X;
                int y = (int)cirarraysub.Center.Y;
                Point pnt1 = new Point(x, y);
                // CircleF roi = new CircleF
                //imagenew.roi = roi;
                //imagenew.Copy()
                CvInvoke.cvCircle(roi.Ptr, pnt1, (int)cirarraysub.Radius, a, -1, LINE_TYPE.EIGHT_CONNECTED, 0);
                //CvInvoke.cvAnd(src, src, res, roi);
                //CvInvoke.cvNot(res, res);
                

                
                //res.Copy(res,roi);

               
            }

            res = src.And(src, roi);
            

            //CvInvoke.cvCopy()

            //res.Not();
            //CvInvoke.cvMerge(roi.Ptr, roi.Ptr, roi.Ptr, IntPtr.Zero, roic3.Ptr);
            //CvInvoke.cvAnd(res, roic3, res, IntPtr.Zero);
            //CvInvoke.cvNot(roi, roi);
            //CvInvoke.cvAdd(src, res, res, roi);

            //String ab = new String();

            //Point pnt1 = new Point(x, y);
            // CircleF roi = new CircleF
            //imagenew.roi = roi;
            //imagenew.Copy()
            //CvInvoke.cvCircle(roi.Ptr, pnt1, 50, a, 1, LINE_TYPE.EIGHT_CONNECTED, 0);
                   

            pic1.Image = roi.ToBitmap();
            pic2.Image = res.ToBitmap();

            #endregion
             */

            /*
            foreach(CircleF cirarraysub in cirarray)
            {
                int x = (int)cirarraysub.Center.X;
                int y = (int)cirarraysub.Center.Y;
                
                
                //String ab = new String();
                
               Point pnt = new Point(x,y);
               // CircleF roi = new CircleF
                //imagenew.roi = roi;
                //imagenew.Copy()
                CvInvoke.cvCircle(roi.Ptr,pnt, 30, a, 2, LINE_TYPE.EIGHT_CONNECTED, 0);
                
                            
            }
             */

            //pic1.Image = imagenew.ToBitmap();
        }

        private void button4_Click(object sender, EventArgs e)
        {
            Image<Gray, Byte> img1 = new Image<Gray, Byte>("phao.jpg");//mau
            Image<Gray, Byte> img2 = new Image<Gray, Byte>("img123.jpg");//tim
            //chessdetect(img1, img2);

        }

        private void button5_Click(object sender, EventArgs e)
        {
            Image<Bgr, Byte> imgtest = new Image<Bgr, Byte>("img123 sized.jpg");
            Image<Bgr, Byte> imgresized = new Image<Bgr, Byte>(circleImageBox.Size);

            imgtest = circledetect(imgtest);
            imgresized = imgtest.Resize(x, y,0);
            //imgresized = circledetect(imgresized);
            circleImageBox.Image = imgresized.ToBitmap();
        }

        private bool checknear(Point bechecked, Point tocheck)
        {
            if (Math.Abs(bechecked.X - tocheck.X) < 10 && Math.Abs(bechecked.Y - tocheck.Y) < 10)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        private string chessdetect(Image<Gray, byte> sourceImage)
        {
            string detected="";
            int i=0;
            Gray colornew = new Gray();
            int angle=0;
            bool flagdetected = false;

    // khai bao ten cua cac template
    #region idenname 

            //nametemplator[2] = "chuot1.png";
            //nametemplator[0] = "phao nho 10.png";
            nametemplator[1] = "phaoxanh1.png";
            nametemplator[2] = "phaodo1.png";
            nametemplator[0] = "chuotxanh1.png";


    #endregion
            while(i<3 && flagdetected!=true)
            {
                Image<Gray, Byte> templateImage = new Image<Gray, Byte>(nametemplator[i]);
                

                for (angle = 0; angle < 3;angle++)
                {

                    templateImage = templateImage.Rotate(angle, colornew);
                    Image<Gray, float> result = sourceImage.MatchTemplate(templateImage, Emgu.CV.CvEnum.TM_TYPE.CV_TM_SQDIFF);

                    // stable
                    Point exam = new Point();
                    exam.X = sourceImage.Height / 2;
                    exam.Y = sourceImage.Width / 2;


                    double[] min, max;
                    Point[] point1, point2;
                    result.MinMax(out min, out max, out point1, out point2);
                    Point point3 = new Point();
                    point3.X = point1[0].X + templateImage.Width;
                    point3.Y = point1[0].Y + templateImage.Height;
                    Point centerpoint = new Point();
                    centerpoint.X = (point1[0].X + point3.X) / 2;
                    centerpoint.Y = (point1[0].Y + point3.Y) / 2;
                    if (checknear(centerpoint, exam)==true)
                    {
                        MCvScalar scalar = new MCvScalar(255);
                        CvInvoke.cvRectangle(sourceImage.Ptr, point1[0], point3, scalar, 1, Emgu.CV.CvEnum.LINE_TYPE.EIGHT_CONNECTED, 0);

                        circleImageBox.Image = sourceImage.ToBitmap();
                        detected = nametemplator[i];
                        i = 2;
                        flagdetected = true;
                        break;

                    }
                    else
                    {
                        MessageBox.Show("Khong tim thay!");
                        flagdetected = false;
                    }
                }

                i++;

            }

            MessageBox.Show("At angle " + angle.ToString());
            return detected;

        }
        private void cmdRotate_Click(object sender, EventArgs e)
        {
            Gray colornew = new Gray();
            Image<Bgr, Byte> imgtest = new Image<Bgr, Byte>("img123.jpg");
            Image<Bgr, Byte> imgresized = new Image<Bgr, Byte>(circleImageBox.Size);

            Image<Gray, Byte> sourceImage = new Image<Gray, Byte>("phao to xoay 10.png");
            Image<Gray, Byte> templateImage = new Image<Gray, Byte>("phao nho chuan.png");
            templateImage = templateImage.Rotate(25,colornew);
            Image<Gray, float> result = sourceImage.MatchTemplate(templateImage, Emgu.CV.CvEnum.TM_TYPE.CV_TM_SQDIFF);

            // stable
            Point exam = new Point();
            exam.X = sourceImage.Height/2;
            exam.Y = sourceImage.Width/2;

            
            double[] min, max;
            Point[] point1, point2;
            result.MinMax(out min, out max, out point1, out point2);
            Point point3 = new Point();
            point3.X = point1[0].X + templateImage.Width;
            point3.Y = point1[0].Y + templateImage.Height;
            Point centerpoint = new Point();
            centerpoint.X = (point1[0].X + point3.X) / 2;
            centerpoint.Y = (point1[0].Y + point3.Y) / 2;
            if (checknear(centerpoint, exam))
            {
                MCvScalar scalar = new MCvScalar(255);
                CvInvoke.cvRectangle(sourceImage.Ptr, point1[0], point3, scalar, 1, Emgu.CV.CvEnum.LINE_TYPE.EIGHT_CONNECTED, 0);

                circleImageBox.Image = sourceImage.ToBitmap();
            }
            else
            {
                MessageBox.Show("Khong tim thay!");
            }
            

           // if (match)
            /*
            imgresized = imgtest.Resize(circleImageBox.Width, circleImageBox.Height, 0);
            Bgr colornew = new Bgr(Color.Black);
            imgresized = imgresized.Rotate(90, colornew);
            circleImageBox.Image = imgresized.ToBitmap();
             * */



            //new code
            /*
            double[] min, max;
            Point[] point1, point2;
            float[, ,] matches = result.Data;
            Bgr colorrect = new Bgr(Color.Blue);
            result.MinMax(out min, out max, out point1, out point2);
            Point point3 = new Point();
            for (int y = 0; y < matches.GetLength(0); y++)
            {
                for (int x = 0; x < matches.GetLength(1); x++)
                {
                    double matchScore = matches[y, x, 0];
                    if (matchScore > 0.75)
                    {
                        Rectangle rect = new Rectangle(new Point(x, y), new Size(1, 1));
                        sourceImage.Draw(rect,colorrect, 1);
                    }

                }

            }
            point3.X = point1[0].X + templateImage.Width;
            point3.Y = point1[0].Y + templateImage.Height;
            MCvScalar scalar = new MCvScalar(255);
            CvInvoke.cvRectangle(sourceImage.Ptr, point1[0], point3, scalar, 1, Emgu.CV.CvEnum.LINE_TYPE.EIGHT_CONNECTED, 0);

            circleImageBox.Image = sourceImage.ToBitmap();
             */
        }

        private void cmdDetect_Click(object sender, EventArgs e)
        {
            Image<Gray, Byte> imgin = new Image<Gray, byte>("173.png");
            
            MessageBox.Show(chessdetect(imgin));
        }

        private void button6_Click(object sender, EventArgs e)
        {
            Image<Gray, Byte> imgsearch = new Image<Gray, Byte>("img123 sized.jpg");
            Image<Bgr, Byte> imgshow = new Image<Bgr, Byte>("img123 sized.jpg");
            string detected;
            /*
            for (int i = 0; i < rectnumber;i++ )
            {
                imgsearch.ROI = recarray[i];
                
            }
             * */
           
                imgsearch.ROI = recarray[14];
                detected = chessdetect(imgsearch);
                //imgsearch.ROI = null;
                imgshow.Draw(detected, ref f, recarray[14].Location, new Bgr(255, 0, 0));
                //imgsearch.Draw(recarray[20], new Bgr(Color.Blue), 2);
                imgshow = imgshow.Resize(x, y, 0);
                circleImageBox.Image = imgshow.ToBitmap();
                //Image<Bgr, Byte> cloned = imgsearch.Clone();
                //cloned.Save("abc.png");
                //Image<Gray, Byte> imgtest = new Image<Gray, Byte>("");
           
        }

        private void pic1_Click(object sender, EventArgs e)
        {

        }
    }
}


